# -*- coding: utf-8 -*-
# @Time    : 2021/8/28 18:08
# @Author  : BrandonGT
# @FileName: 03-PyQt5_QObject.py
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *


class Window(QWidget):
    def __init__(self):
        super().__init__()  # 初始化继承的父类内部的__init__
        self.setWindowTitle("QObject的学习")
        self.resize(300, 300)
        self.setup_ui()

    def setup_ui(self):
        # self.QObject_structure()
        # self.QObject_name_value()
        # self.QObject_signal_slot()
        # self.QObject_is_type()
        self.QObject_del()

    def QObject_structure(self):  #  QObject 继承结构测试
        # QObject.__subclasses__()  # 获取类的子类
        mros = QObject.mro()  # .mro() 获取类的父类
        for mro in mros:
            print(mro)

    def QObject_name_value(self):  #  QObject 对象名称和属性的操作
        # ------------------测试API ------------------ 开始
        # obj = QObject()
        # obj.setObjectName("BrandonGT")  # 设置Qt对象的名称
        # print(obj.objectName())  # 获取Qt对象的名称
        # 
        # obj.setProperty("notic_level", "error")  # 给Qt对象动态的添加一个属性和值
        # obj.setProperty("notic_level2", "warning")
        # 
        # print(obj.property("notic_level"))  # 获取一个Qt对象的属性值
        # print(obj.dynamicPropertyNames())  # 获取一个Qt对象中所有通过setProperty添加的属性名称
        # ------------------测试API ------------------ 结束

        # ------------------API-案例 ------------------ 开始
        with open("code_03_QObject.qss", "r") as f:
            qApp.setStyleSheet(f.read())  # 将qss文件的样式，整体加载与全局的qApp中

        label = QLabel(self)
        label.setObjectName("notice")  # 配合code_03_QObject.qss 看
        label.setProperty("notice_level", "normal")  # 配合code_03_QObject.qss 看
        label.setText("API测试")

        label2 = QLabel(self)
        label2.setObjectName("notice")  # 配合code_03_QObject.qss 看
        label2.setProperty("notice_level", "warning")  # 配合code_03_QObject.qss 看
        label2.setText("BrandonGT")
        label2.move(200, 200)

        # label.setStyleSheet("font-size: 20px; color: red")
        # ------------------API-案例 ------------------ 结束

    def QObject_signal_slot(self):  # QObject信号的操作
        self.obj = QObject()
        # obj = QObject(self)  # 以上两种写法是有区别的

        # 以下是QObject自带的两个信号
        # obj.destroyed
        # obj.objectNameChanged

        def when_destoryed(obj):
            print("signal destoryed!", obj)

        def when_nameChanged_A(obj):
            print("Name ChangedA", obj)

        def when_nameChanged_B(obj):
            print("Name ChangedB", obj)

        # self.obj.destroyed.connect(when_destoryed)  # destoryes可以传递一个变量至slot里
        # obj.destroyed.connect(when_destoryed)  # 以上两种写法是有区别的

        self.obj.objectNameChanged.connect(when_nameChanged_A)
        # self.obj.objectNameChanged.connect(when_nameChanged_B)

        self.obj.setObjectName("Name A")

        # self.obj.objectNameChanged.disconnect()  # 如果disconnect括号中不指定函数的话，则会断开所有的连接
        # self.obj.objectNameChanged.disconnect(when_nameChanged_A)  # 如果指定的话只会断开指定的slot函数

        # self.obj.blockSignals(True)
        # print(self.obj.signalsBlocked())  # 用于查看signal是否被屏蔽了

        # print(self.obj.receivers(self.obj.objectNameChanged))  # 需要的是控件连接的信号类型

        self.obj.setObjectName("Name B")

        # self.obj.blockSignals(False)

        self.obj.setObjectName("Name C")

        # del self.obj
        # del obj  # 以上两种写法是有区别的，目前不知道怎么在运行中，删除子控件


        # ------------------用来搞清楚self. 和（self）的区别 ------------------ 开始
        # self.label = QLabel()
        # self.label.setText("self.label")
        # self.label.setParent(self)
        # # self.在前定义的函数，只不过是将指针指向变量，确保在创建后不会因为自动释放机制，而被自动释放掉
        # # （self）是将创建的内容直接绑定成子对象，所以也不会被自动释放，且效果与setParent()相同
        # label = QLabel(self)
        # label.setText("label add self")
        # label.move(100, 50)
        # ------------------用来搞清楚self. 和（self）的区别 ------------------ 结束

    def QObject_is_type(self):  # QObject的类型的判断
        # obj = QObject()
        # btn = QPushButton()
        # label = QLabel()
        #
        # objs = [obj, btn, label]
        # for o in objs:
        #     # print(o.isWidgetType())  # 返回遍历的对象是否是Widget的类型
        #     print(o.inherits("QObject"))  # 返回遍历的对象是否直接或者间接的继承自指定的对象

        # ------------------案例：控件过滤 ------------------ 开始
        label_01 = QLabel(self)
        label_01.setText("Label 01")
        label_01.move(50, 50)

        label_02 = QLabel(self)
        label_02.setText("Label 02")
        label_02.move(100, 100)

        btn_01 = QPushButton(self)
        btn_01.setText("Button 01")
        btn_01.move(150, 150)

        for wids in self.children():
            print(wids)
            if wids.inherits("QLabel"):
                wids.setStyleSheet("color: cyan")
        # ------------------案例：控件过滤 ------------------ 结束

    def QObject_del(self):  # 如何删除对象
        self.w = QWidget()

        obj1 = QLabel(self)
        obj1.setText("Label 01")
        obj1.move(0, 0)

        obj2 = QLabel(obj1)
        obj2.setText("Label 02")
        obj2.move(50, 50)

        obj3 = QLabel(obj2)
        obj3.setText("Label 03")
        obj3.move(100, 100)

        obj2.deleteLater()  # 解答了之前的问题，del只是打断了变量与对象的关系，并没有删除对象
        #  所以要删除对象，需要使用deleteLater（）
        print(obj2)  # 且因为是在下一次循环之后才会删除，所以deleteLater之后的命令也会执行

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = Window()
    window.show()

    # ------------------案例：父子管理 ------------------ 开始
    # win_root = QWidget()
    # win_root.resize(500, 500)
    #
    # label_01 = QLabel(win_root)
    # label_01.move(0, 0)
    # label_01.setFixedSize(100, 50)
    # label_01.setText("Label 01")
    #
    # label_02 = QLabel(win_root)
    # label_02.move(50, 50)
    # label_02.setFixedSize(100, 50)
    # label_02.setText("Label 02")
    #
    # label_03 = QLabel(win_root)
    # label_03.move(100, 100)
    # label_03.setFixedSize(100, 50)
    # label_03.setText("Label 03")
    #
    # btn_01 = QPushButton(win_root)
    # btn_01.move(150, 200)
    # btn_01.setFixedSize(100, 50)
    # btn_01.setText("Button 01")
    #
    # for sub_par in win_root.findChildren(QLabel):
    #     sub_par.setStyleSheet("background: red")
    #
    # win_root.show()
    # ------------------案例：父子管理 ------------------ 结束


    sys.exit(app.exec_())
